CodeSandbox example https://codesandbox.io/s/throbbing-worker-8s68n?file=/src/index.js
So I have an object and I'm updating the key name by removing the __number, I want to move the the 1st key [ 694 & 695 ] to inside the object as id = 694. I didn't manage to make that happen cause I get a new object for each key value ( see code below ).
var options =
{
"694": {
"title_694": "Tiger",
"category_694": "848",
"description_694": "long description"
},
"695": {
"title_694": "Turtles",
"category_694": "347",
"description_694": "long description"
}
}
and here is my code
Object.keys(options).map( value => (
{
[value] : Object.keys(options[value]).map((keyName) => (
{[keyName.replace(/_*\d+/g, '')] : options[value][keyName]}
))
}
)
)
it output as below
[
{
"694": [
{
"title": "Tiger"
},
{
"category": "848"
},
{
"description": "long description"
}
]
},
{
"695": [
{
"title": "Turtles"
},
{
"category": "347"
},
{
"description": "long description"
}
]
}
]
How can make it work to output as below
[
{
"id": 694,
"title": "Tiger",
"category": "848",
"description": "long description"
},
{
"id":695,
"title": "Turtles",
"category": "347",
"description": "long description"
}
]
There is a way to do it without map :
var result = [];
Object.keys(options).forEach((element) => {
result.push({ id: element, ...options[element] });
});
Output:
[
{
"id": "694",
"title_694": "Tiger",
"category_694": "848",
"description_694": "long description"
},
{
"id": "695",
"title_694": "Turtles",
"category_694": "347",
"description_694": "long description"
}
]
Ask me if you have more questions. But you need more code to remove id from new keys object
Using forEach without changing the key names in the original object
var result = [];
Object.keys(options).forEach((element) => {
const item = Object.fromEntries(
Object.entries(options[element]).map(([k, v]) => {
k = k.replace(/_*\d+/g, "");
return [k, v]
})
)
result = [...result,{ id: element, ...item }]
// Or you could use push which is slightly faster
// To see benchmarks Google Spread operator vs push site: measurethat.net
// result.push({ id: element, ...options[element] });
});
document.getElementById("app").innerHTML = `<pre>${JSON.stringify(
result,
null,
4
)}</pre>`;
console.log(result);
The output
[
{
"id": "694",
"title": "Tiger",
"category": "848",
"description": "long description"
},
{
"id": "695",
"title": "Turtles",
"category": "347",
"description": "long description"
}
]
Personally like you, I prefer not to manually build a whole new array.
var options = {
"694": {
"title_694": "Tiger",
"category_694": "848",
"description_694": "long description"
},
"695": {
"title_694": "Turtles",
"category_694": "347",
"description_694": "long description"
}
}
let mutated = Object.values(Object.entries(options).map(([id, option]) => {
return Object.assign({
id: id,
}, Object.fromEntries(Object.entries(option).map(([key, value]) => {
return [key.replace(/_*\d+$/g, ''), value];
})));
}));
This lets the first map function create a new array accordingly, Object.assign ensures you have a single object from each, and the Object.entries and Object.fromEntries to convert to an array of pairs to then convert the keys, and then back from the array of pairs.
Have a read of the MDN documentation relating to Object.entries: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/entries
That links to the Object.fromEntries documentation, too.
As a side note, I've modified your regular expression to include the end-of-line match so it will modify something like w3tag_694 in the expected way. I would also suggest looking at changing the * in the regex to a + to be a little stricter.
There is a caveat: fromEntries is a relatively new feature, but is supported by all major browsers still supported by their makers. Check the support: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/fromEntries#browser_compatibility